package com.xiaogang.ggfw.utils.common;

import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Closeable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class SimpleTools {
    private static SimpleTools simpleTools;

    private static CustomJsonMapper jsonMapper;
    private static CustomJsonMapper jsonMapperIncludeNull;

    static {
        jsonMapper = CustomJsonMapper.getDefault();
        jsonMapperIncludeNull = new CustomJsonMapper();
        jsonMapperIncludeNull.setSerializationInclusion(JsonInclude.Include.ALWAYS);
    }

    public static CustomJsonMapper jsonMapper(boolean includeNull) {
        return includeNull ? jsonMapperIncludeNull : jsonMapper;
    }

    /**
     * 判断是否是int
     *
     * @param str
     * @return
     */
    public static boolean isInt(String str) {
        return null != str && str.matches("\\d+");
    }

    public static SimpleTools getInstance() {
        if (simpleTools == null) {
            simpleTools = new SimpleTools();
        }
        return simpleTools;
    }

    /**
     * 四舍五入保留
     *
     * @param d
     * @param digits
     * @return
     */
    public String formatDouble(double d, int digits) {
        NumberFormat nf = NumberFormat.getNumberInstance();
        // 保留两位小数
        nf.setMaximumFractionDigits(digits);
        // 如果不需要四舍五入，可以使用RoundingMode.DOWN
        nf.setRoundingMode(RoundingMode.HALF_UP);
        return nf.format(d);
    }

    /**
     * 四舍五入保留2位小数
     *
     * @param d
     * @return
     */
    public String formatDouble2(double d) {
        return formatDouble(d, 2);
    }

    public static void responseJsonString(HttpServletResponse response, Object msg) {
        responseJsonString(HttpStatus.OK, response, msg);
    }

    public static void responseJsonString(HttpStatus httpStatus, HttpServletResponse response, Object msg) {
        try {
            String realMsg = null;
            if (msg == null) {
                realMsg = "";
            } else {
                if (msg instanceof String) {
                    realMsg = String.valueOf(msg);
                } else {
                    realMsg = CustomJsonMapper.getDefault().writeValueAsString(msg);
                }
            }
            response.setStatus(httpStatus.value());// HttpStatus.OK
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");// application/json;
            // charset=utf-8
            response.getWriter().print(realMsg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String base64Encode(Object dataObj) {
        String data = null;
        if (dataObj == null) {
            return data;
        }
        if (dataObj instanceof String) {
            data = String.valueOf(dataObj);
        } else {
            data = CustomJsonMapper.getDefault().writeValueAsString(dataObj);
        }
        if (null != data)
            data = Base64Utils.encodeToString(data.getBytes(StandardCharsets.UTF_8));
        return data;
    }


    public static int compareString(Object obj1, Object obj2) {
        String str1 = null;
        String str2 = null;

        if (null != obj1) {
            str1 = String.valueOf(obj1);
        }

        if (null != obj2) {
            str2 = String.valueOf(obj2);
        }

        if (str1 == null || str2 == null) {
            if (str1 == null && str2 == null) {
                return 0;
            } else if (str1 == null && str2 != null) {
                return -1;
            } else {
                return 1;
            }
        } else {
            return str1.compareTo(str2);
        }
    }

    //获取后几位字符串
    public static String getLastStringByLen(String str, int len) {
        if (null == str || str.length() <= len) {
            return str;
        }
        return str.substring(str.length() - len);
    }

    public static boolean isNullOrBlank(String str) {
        if (str != null)
            str = str.trim();
        return null == str || str.length() <= 0;
    }

    /**
     * 将空字符串转null返回，否则返回原字符串。
     *
     * @param str
     * @return
     */
    public static String blankToNull(String str) {
        return isNullOrBlank(str) ? null : str;
    }

    /**
     * 将空字符串""替换为null
     *
     * @param obj
     */
    public static void blankStrFieldToNull(Object obj) {
        if (null == obj) {
            return;
        }
        if (obj instanceof List) {
            List list = (List) obj;
            for (Object ele : list) {
                blankStrFieldToNull(ele);
            }
            return;
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field f : fields) {
            try {
                f.setAccessible(true);
                Object val = f.get(obj);
                if (val != null && val instanceof String) {
                    if (isNullOrBlank(String.valueOf(val))) {
                        f.set(obj, null);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static String base64Decode(String src) {
        return base64Decode(src, null);
    }

    public static String base64Decode(String src, String charset) {
        if (null == src) return src;
        if (charset == null) charset = "UTF-8";
        try {
            return new String(Base64Utils.decodeFromString(src), charset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Object jsonDemoObj(Class type) {
        if (type == null || type.equals(Object.class)) {
            return "{}";
        }
        Object obj = null;
        try {
            obj = type.newInstance();
            Field[] fields = type.getDeclaredFields();
            if (fields != null) {
                for (Field f : fields) {
                    f.setAccessible(true);
                    Class fieldType = f.getType();
                    if (isBaseType(fieldType)) {
                        f.set(obj, jsonDemoDefaultValue(fieldType));
                    } else {
                        if (fieldType.isAssignableFrom(List.class)) {
//                            Class[] geneicClass = getGenericSuperclass(fieldType);
//                            System.out.println(geneicClass[0]);
                            List list = new ArrayList();
//                            list.add();
                            f.set(obj, list);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

    public static boolean isBaseType(Class fieldType) {
        return fieldType.equals(byte.class)
                || fieldType.equals(Byte.class)
                || fieldType.equals(short.class)
                || fieldType.equals(Short.class)
                || fieldType.equals(int.class)
                || fieldType.equals(Integer.class)
                || fieldType.equals(Long.class)
                || fieldType.equals(long.class)
                || fieldType.equals(double.class)
                || fieldType.equals(Double.class)
                || fieldType.equals(float.class)
                || fieldType.equals(Float.class)
                || fieldType.equals(String.class);


    }

    private static Object jsonDemoDefaultValue(Class fieldType) {
        if (fieldType.equals(byte.class)
                || fieldType.equals(Byte.class)
                || fieldType.equals(short.class)
                || fieldType.equals(Short.class)
                || fieldType.equals(int.class)
                || fieldType.equals(Integer.class)
                || fieldType.equals(Long.class)
                || fieldType.equals(long.class)) {
            return (int) Math.round(Math.random());
        }
        if (fieldType.equals(double.class)
                || fieldType.equals(Double.class)
                || fieldType.equals(float.class)
                || fieldType.equals(Float.class)
                || fieldType.equals(BigDecimal.class)) {
            return (float) ((Math.random() * 100) / 10);
        }
        if (fieldType.equals(String.class)
                || fieldType.equals(StringBuilder.class)) {
            return UUID.randomUUID().toString();
        }
        return null;
    }

    /**
     * 获取父类型的泛型。
     *
     * @param mClass
     * @return
     */
    public static Class[] getGenericSuperclass(Class mClass) {
        Type type = mClass.getGenericSuperclass();
        while (!(type instanceof Class)) {
            if (type instanceof WildcardType) {
                type = ((WildcardType) type).getUpperBounds()[0];
            } else if (type instanceof TypeVariable<?>) {
                type = ((TypeVariable<?>) type).getBounds()[0];
            } else if (type instanceof ParameterizedType) {
                ParameterizedType ptype = (ParameterizedType) type;
                Type[] types = ptype.getActualTypeArguments();
                if (types == null || types.length == 0) {
                    return new Class[]{Object.class};
                }
                Class[] rs = new Class[types.length];
                for (int i = 0; i < types.length; i++) {
                    rs[i] = (Class) types[i];
                }
                return rs;
            } else if (type instanceof GenericArrayType) {
                type = ((GenericArrayType) type).getGenericComponentType();
            }
        }
        return new Class[]{(Class) type};
    }

    public static HttpServletRequest getRequest() {
        HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return req;
    }

    public static HttpServletResponse getResponse() {
        HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        return resp;
    }

    public static void close(Closeable closeable) {
        try {
            if (null != closeable)
                closeable.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 返回一个下载的实体类
     *
     * @param data
     * @param name
     * @return
     */
    public static ResponseEntity downloadEntity(byte[] data, String name) {
        ResponseEntity entity = null;
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name, "utf-8"));
            entity = new ResponseEntity(data, headers, HttpStatus.OK);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return entity;
    }

    public static boolean isNotEmpty(String str) {
        return !StringUtils.isEmpty(str);
    }

    public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f",
            "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
            "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
            "W", "X", "Y", "Z" };

    public static String generateShortUuid() {
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        for (int i = 0; i < 8; i++) {
            String str = uuid.substring(i * 4, i * 4 + 4);
            int x = Integer.parseInt(str, 16);
            shortBuffer.append(chars[x % 0x3E]);
        }
        return shortBuffer.toString();

    }


}
